use axum::{
    extract::{Query, State},
    http::StatusCode,
    response::IntoResponse,
    Json,
};
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
use tracing::{info, error, warn, debug};
use crate::error::{AppError, AppResult};
use crate::models::{WeChatMessage, WeChatEncryptedRequest, WeChatResponse};
use crate::routes::AppState;
use crate::utils::WxCrypto;
use rand::Rng;

#[derive(Debug, Deserialize, ToSchema)]
pub struct VerifyQuery {
    msg_signature: String,
    timestamp: String,
    nonce: String,
    echostr: String,
}

#[derive(Debug, Deserialize, ToSchema)]
pub struct CallbackQuery {
    msg_signature: String,
    timestamp: String,
    nonce: String,
}

/// 企业微信 URL 验证
#[utoipa::path(
    get,
    path = "/callback",
    tag = "wechat",
    params(
        ("msg_signature" = String, Query, description = "消息签名"),
        ("timestamp" = String, Query, description = "时间戳"),
        ("nonce" = String, Query, description = "随机数"),
        ("echostr" = String, Query, description = "加密的验证字符串"),
    ),
    responses(
        (status = 200, description = "解密后的验证字符串", body = String),
        (status = 400, description = "验证失败"),
    )
)]
pub async fn verify_url(
    State(state): State<AppState>,
    Query(query): Query<VerifyQuery>,
) -> AppResult<impl IntoResponse> {
    info!("[GET /callback] Verifying URL");
    
    let crypto = WxCrypto::new(
        state.config.wx_token.clone(),
        state.config.wx_encoding_aes_key.clone(),
        "".to_string(),
    )?;
    
    // 验证签名
    let signature_valid = crypto.verify_signature(
        &query.msg_signature,
        &query.timestamp,
        &query.nonce,
        &query.echostr,
    )?;
    
    if !signature_valid {
        warn!("[GET /callback] Signature verification failed!");
        return Err(AppError::CryptoError("Invalid signature".to_string()));
    }
    
    // 解密 echostr
    let decrypted = crypto.decrypt(&query.echostr)?;
    info!("[GET /callback] URL verification successful");
    
    Ok(decrypted)
}

/// 接收企业微信加密消息
#[utoipa::path(
    post,
    path = "/callback",
    tag = "wechat",
    request_body = WeChatEncryptedRequest,
    responses(
        (status = 200, description = "处理成功，返回加密响应", body = serde_json::Value),
        (status = 400, description = "请求无效或签名验证失败"),
    )
)]
pub async fn handle_message(
    State(state): State<AppState>,
    Query(query): Query<CallbackQuery>,  // 签名参数在 query 中，必须提供
    body: Result<Json<WeChatEncryptedRequest>, axum::extract::rejection::JsonRejection>,
) -> AppResult<impl IntoResponse> {
    info!("[POST /callback] Received request");
    
    // 处理 JSON 解析错误
    let Json(req) = body.map_err(|e| {
        error!("[POST /callback] Failed to parse JSON body: {}", e);
        AppError::ParseError(format!("Invalid JSON: {}", e))
    })?;
    
    debug!("[POST /callback] Request body: encrypt_len={}", req.encrypt.len());
    debug!("[POST /callback] Query params: msg_signature={}, timestamp={}, nonce={}",
        query.msg_signature, query.timestamp, query.nonce);
    debug!("[POST /callback] Config: wx_token={}, wx_encoding_aes_key_len={}",
        state.config.wx_token, state.config.wx_encoding_aes_key.len());
    
    let crypto = WxCrypto::new(
        state.config.wx_token.clone(),
        state.config.wx_encoding_aes_key.clone(),
        "".to_string(),
    )?;
    debug!("[POST /callback] WxCrypto initialized successfully");
    
    // 验证签名
    debug!("[POST /callback] Verifying signature...");
    let signature_valid = crypto.verify_signature(
        &query.msg_signature,
        &query.timestamp,
        &query.nonce,
        &req.encrypt,
    )?;
    
    if !signature_valid {
        warn!("[POST /callback] Signature verification failed!");
        debug!("[POST /callback] Expected signature: {}", query.msg_signature);
        return Err(AppError::CryptoError("Invalid signature".to_string()));
    }
    debug!("[POST /callback] Signature verified successfully");
    
    // 解密消息
    debug!("[POST /callback] Decrypting message...");
    let decrypted_msg = crypto.decrypt(&req.encrypt)?;
    info!("[POST /callback] Decrypted message: {}", decrypted_msg);
    
    // 解析消息
    debug!("[POST /callback] Parsing WeChat message...");
    let wechat_msg: WeChatMessage = serde_json::from_str(&decrypted_msg)
        .map_err(|e| {
            error!("[POST /callback] Failed to parse message: {}", e);
            debug!("[POST /callback] Raw decrypted message: {}", decrypted_msg);
            AppError::ParseError(format!("Failed to parse WeChat message: {}", e))
        })?;
    debug!("[POST /callback] Parsed message: from_user={}, msg_type={}, content={:?}",
        wechat_msg.from.userid, wechat_msg.msgtype, 
        wechat_msg.text.as_ref().map(|t| &t.content));
    
    // 转发到 reminder 处理
    debug!("[POST /callback] Forwarding to reminder handler...");
    
    // 检查消息是否已在处理中（去重）
    if state.msg_cache.is_processing(&wechat_msg.msgid) {
        info!("[POST /callback] Message {} is already being processed, ignoring duplicate", wechat_msg.msgid);
        
        // 返回空响应（普通 JSON，不加密）
        let empty_response = WeChatResponse::new_text("".to_string());
        let response_json = serde_json::to_value(&empty_response)
            .map_err(|e| AppError::InternalError(format!("Failed to serialize response: {}", e)))?;
        
        return Ok(Json(response_json));
    }
    
    // 标记消息为处理中
    state.msg_cache.mark_processing(&wechat_msg.msgid);
    
    let response_msg = match forward_to_reminder(&state, wechat_msg.clone()).await {
        Ok(msg) => {
            debug!("[POST /callback] Reminder processed successfully");
            msg
        },
        Err(e) => {
            error!("[POST /callback] Failed to process reminder: {}", e);
            WeChatResponse::new_text(format!("处理失败: {}", e))
        }
    };
    
    // 处理完成后从缓存中删除
    state.msg_cache.remove(&wechat_msg.msgid);
    
    // ⚠️ 重要：企业微信回调响应不需要加密，直接返回 JSON 即可
    // 参考 Python 版本：return {"content": reply_content}
    info!("[POST /callback] Message processed successfully, returning plain JSON");
    
    // 转换为 JSON值
    let response_json = serde_json::to_value(&response_msg)
        .map_err(|e| {
            error!("[POST /callback] Failed to serialize response: {}", e);
            AppError::InternalError(format!("Failed to serialize response: {}", e))
        })?;
    
    Ok(Json(response_json))
}

/// 转发消息到 reminder 处理器
async fn forward_to_reminder(
    state: &AppState,
    wechat_msg: WeChatMessage,
) -> AppResult<WeChatResponse> {
    use crate::routes::reminder;
    
    // 调用 reminder 处理逻辑
    reminder::process_message(state, wechat_msg).await
}

/// 生成随机 nonce
fn generate_nonce() -> String {
    use rand::Rng;
    let mut rng = rand::thread_rng();
    (0..16)
        .map(|_| rng.sample(rand::distributions::Alphanumeric) as char)
        .collect()
}
